
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <deque>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <algorithm>
#include <numeric>
#include <limits>
#include <cmath>

#include <lurpc/net/socket_server.h>
#include <lurpc/core/rpc_core.h>
#include <lurpc/service/server_stub.h>


/**
 * Define base functions.
 */
namespace tmp_kv_server {

class db {
public:
    std::unordered_map<std::string, std::string> __db_;

public:
    int set_string(const std::string& _key, const std::string& _val) {
        __db_[_key] = _val;
        return 0;
    }

    std::string get_string(const std::string& _key) {
        return (__db_.find(_key) == __db_.end() ? "[NON]" : __db_[_key]);
    }

};

db __db_;

}


/**
 * Define services.
 */
namespace tmp_kv_server {

std::string service_101(const std::string& _msg) {
    using serial_type_tr = lurpc::service_type_traits<int, std::string, std::string>;
    auto param_tp = serial_type_tr::deserialize(_msg);
    auto result = __db_.set_string(std::get<0>(param_tp), std::get<1>(param_tp));
    return serial_type_tr::serialize(result);
}

std::string service_102(const std::string& _msg) {
    using serial_type_tr = lurpc::service_type_traits<std::string, std::string>;
    auto param_tp = serial_type_tr::deserialize(_msg);
    auto result = __db_.get_string(std::get<0>(param_tp));
    return serial_type_tr::serialize(result);
}

}


/**
 * Register service to framework and start server.
 */
namespace tmp_kv_server {

void register_service() {
    lurpc::server_stub::register_service(101, service_101);
    lurpc::server_stub::register_service(102, service_102);
}

void start() {
    lurpc::start_rpc_server(4399, "127.0.0.1");
}

}


int main() {

    tmp_kv_server::register_service();
    tmp_kv_server::start();

    return 0;
}
